﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation;

namespace TeachView3D
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    /// 



    public partial class MainWindow : Window
    {

        public double SpeedFactor = 1, AnimationFactor = 1;
        PerspectiveCamera myPCamera = new PerspectiveCamera();
        private Point mouseLastPosition;
        public double mouseDeltaFactor = 2;
        private Point3D lookatPoint;
        public MainWindow()
        {
             InitializeComponent();
            lookatPoint = new Point3D(0, 600, 0);

            myPCamera.Position = new Point3D(0, 600, 2000);
            myPCamera.LookDirection = new Vector3D(0, 0, -2000);
            myPCamera.FieldOfView = 45;
            myPCamera.UpDirection = new Vector3D(0,1,0);
            scene.Camera = myPCamera;




        }

        private void TransformModel()
        {

        }

        private void scene_MouseMove(object sender, MouseEventArgs e)
        {
            if (Mouse.LeftButton == MouseButtonState.Pressed)//如果按下鼠标左键--旋转
            {

                Point newMousePosition = e.GetPosition(this);
                if (mouseLastPosition.X != newMousePosition.X)
                {
                    //进行水平旋转
                    HorizontalTransform(mouseLastPosition.X < newMousePosition.X, mouseDeltaFactor);//水平变换
                }
                if (mouseLastPosition.Y != newMousePosition.Y)// change position in the horizontal direction
                {
                    //进行垂直旋转
                    VerticalTransform(mouseLastPosition.Y > newMousePosition.Y, mouseDeltaFactor);//垂直变换 
                }
                mouseLastPosition = newMousePosition;

            }
            if (Mouse.MiddleButton == MouseButtonState.Pressed)
            {
                Point newMousePosition = e.GetPosition(this);

                if (mouseLastPosition.X != newMousePosition.X)
                {
                    //进行水平旋转
                    HorizontalTranslate(mouseLastPosition.X < newMousePosition.X, mouseDeltaFactor);//水平平移
                }
                if (mouseLastPosition.Y != newMousePosition.Y)// change position in the horizontal direction
                {
                    //进行垂直旋转
                    VerticalTranslate(mouseLastPosition.Y > newMousePosition.Y, mouseDeltaFactor);//垂直平移 
                }
                mouseLastPosition = newMousePosition;

            }

            
        }

        private void scene_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            double scaleFactor = 10;
            //120 near ,   -120 far
            System.Diagnostics.Debug.WriteLine(e.Delta.ToString());
            Point3D currentPosition = myPCamera.Position;
            Vector3D lookDirection = myPCamera.LookDirection;//new Vector3D(camera.LookDirection.X, camera.LookDirection.Y, camera.LookDirection.Z);
            lookDirection.Normalize();
            lookDirection *= scaleFactor * SpeedFactor;
            if (e.Delta == 120)//getting near
            {
                //myPCamera.FieldOfView /= 1.2;
                if ((currentPosition.X + lookDirection.X) * currentPosition.X >= 0)
                {
                    currentPosition += lookDirection;
                }
            }
            if (e.Delta == -120)//getting far
            {
                //myPCamera.FieldOfView *= 1.2;
                currentPosition -= lookDirection;
            }

            Point3DAnimation positionAnimation = new Point3DAnimation();
            positionAnimation.BeginTime = new TimeSpan(0, 0, 0);
            positionAnimation.Duration = TimeSpan.FromMilliseconds(100);
            positionAnimation.To = currentPosition;
            positionAnimation.From = myPCamera.Position;
            positionAnimation.Completed += new EventHandler(positionAnimation_Completed);
            myPCamera.BeginAnimation(PerspectiveCamera.PositionProperty, positionAnimation, HandoffBehavior.Compose);
        }
        void positionAnimation_Completed(object sender, EventArgs e)
        {
            Point3D position = myPCamera.Position;
            myPCamera.BeginAnimation(PerspectiveCamera.PositionProperty, null);
            myPCamera.Position = position;

        }

        // 垂直旋转
        private void VerticalTransform(bool upDown, double angleDeltaFactor)
        {
            Vector3D postion = new Vector3D(myPCamera.Position.X, myPCamera.Position.Y, myPCamera.Position.Z);
            Vector3D rotateAxis = Vector3D.CrossProduct(postion, myPCamera.UpDirection);
            RotateTransform3D rt3d = new RotateTransform3D();
            AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, angleDeltaFactor * SpeedFactor * (upDown ? -1 : 1));
            rt3d.Rotation = rotate;
            Matrix3D matrix = rt3d.Value;
            Point3D newPostition = matrix.Transform(myPCamera.Position);
            myPCamera.Position = newPostition;
            myPCamera.LookDirection = new Vector3D(lookatPoint.X - newPostition.X, lookatPoint.Y - newPostition.Y, lookatPoint.Z - newPostition.Z);
            //update the up direction
            Vector3D newUpDirection = Vector3D.CrossProduct(myPCamera.LookDirection, rotateAxis);
            newUpDirection.Normalize();
            myPCamera.UpDirection = newUpDirection;
        }
        // 水平旋转
        private void HorizontalTransform(bool leftRight, double angleDeltaFactor)
        {
            Vector3D postion = new Vector3D(myPCamera.Position.X, myPCamera.Position.Y, myPCamera.Position.Z);//当前摄像头的位置
            Vector3D rotateAxis = myPCamera.UpDirection;//获取摄像机向上方向的向量
            RotateTransform3D rt3d = new RotateTransform3D();//旋转变换
            AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, angleDeltaFactor * SpeedFactor * (leftRight ? -1 : 1));
            rt3d.Rotation = rotate;
            Matrix3D matrix = rt3d.Value;
            Point3D newPostition = matrix.Transform(myPCamera.Position);
            myPCamera.Position = newPostition;
            myPCamera.LookDirection = new Vector3D(lookatPoint.X - newPostition.X, lookatPoint.Y - newPostition.Y, lookatPoint.Z - newPostition.Z);
        }

        //垂直平移
        private void VerticalTranslate(bool upDown, double angleDeltaFactor)
        {
            Vector3D position = new Vector3D(myPCamera.Position.X, myPCamera.Position.Y, myPCamera.Position.Z);
            /*
            Vector3D rotateAxis = Vector3D.CrossProduct(position, myPCamera.UpDirection);
            RotateTransform3D rt3d = new RotateTransform3D();
            AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, angleDeltaFactor * (upDown ? -1 : 1));
            rt3d.Rotation = rotate;
            Matrix3D matrix = rt3d.Value;*/
            Vector3D direction = myPCamera.UpDirection;
            direction.Normalize();
            double offsetx = direction.X * angleDeltaFactor * SpeedFactor * (upDown ? -1 : 1);
            double offsety = direction.Y * angleDeltaFactor * SpeedFactor * (upDown ? -1 : 1);
            double offsetz = direction.Z * angleDeltaFactor * SpeedFactor * (upDown ? -1 : 1);
            Point3D newPostition = new Point3D(position.X + offsetx, position.Y + offsety, position.Z + offsetz);
            myPCamera.Position = newPostition;
            lookatPoint = new Point3D(lookatPoint.X + offsetx, lookatPoint.Y + offsety, lookatPoint.Z + offsetz);
            //update the up direction
        }
        // 水平平移
        private void HorizontalTranslate(bool leftRight, double angleDeltaFactor)
        {
            Vector3D position = new Vector3D(myPCamera.Position.X, myPCamera.Position.Y, myPCamera.Position.Z);//当前摄像头的位置
            Vector3D veclook = myPCamera.LookDirection;//获取摄像机向上方向的向量
            Vector3D vecup = myPCamera.UpDirection;
            Vector3D direction = Vector3D.CrossProduct(vecup, veclook);
            direction.Normalize();
            /*
            RotateTransform3D rt3d = new RotateTransform3D();//旋转变换
            AxisAngleRotation3D rotate = new AxisAngleRotation3D(rotateAxis, 90);
            rt3d.Rotation = rotate;
            Matrix3D matrix = rt3d.Value;*/
            double offsetx = direction.X * angleDeltaFactor * SpeedFactor * (leftRight ? 1 : -1);
            double offsety = direction.Y * angleDeltaFactor * SpeedFactor * (leftRight ? 1 : -1);
            double offsetz = direction.Z * angleDeltaFactor * SpeedFactor * (leftRight ? 1 : -1);
            Point3D newPostition = new Point3D(position.X + offsetx, position.Y + offsety, position.Z + offsetz);
            myPCamera.Position = newPostition;
            lookatPoint = new Point3D(lookatPoint.X + offsetx, lookatPoint.Y + offsety, lookatPoint.Z + offsetz);
        }
    }
}
